package com.anorak.betsy.util;

import com.anorak.betsy.entity.Verify;
import sun.misc.BASE64Decoder;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author anorak
 */
public class VerifyUtil {

    public static Integer verifyDecrypt(Verify verify) throws IOException {
        String all = verify.getOriginalImageBase64();
        String one = verify.getJigsawImageBase64();
        int integer = 0;
        BufferedImage imageOne = bufferedImage(one);
        Map<Integer, List<Integer>> nums = new HashMap<>();
        for (int y = 0; y < imageOne.getHeight(); y++) {
            for (int x = 0; x < imageOne.getWidth(); x++) {
                if (imageOne.getRGB(x, y) == -1) {
                    imageOne.setRGB(x, y, -65536);
                    if (nums.get(y) != null) {
                        List<Integer> integers = nums.get(y);
                        integers.add(x);
                        nums.put(y, integers);
                    } else {
                        List<Integer> integers = new ArrayList<>();
                        integers.add(x);
                        nums.put(y, integers);
                    }
                }
            }
        }
        BufferedImage imageAll = bufferedImage(all);
        for (int i = 0; i < 263; i++) {
            AtomicBoolean flag = new AtomicBoolean(true);
            int finalI = i;
            nums.forEach((k, v) -> {
                int min = Collections.min(v);
                int rgbMin = imageAll.getRGB(min + finalI, k);
                if (rgbMin != -1) {
                    flag.set(false);
                }
            });
            if (flag.get()) {
                integer = i;
                break;
            }
        }
        if (integer == 0) {
            for (int i = 0; i < 263; i++) {
                AtomicBoolean flag = new AtomicBoolean(true);
                int finalI = i;
                nums.forEach((k, v) -> {
                    int max = Collections.max(v);
                    int rgbMax = imageAll.getRGB(max + finalI, k);
                    if (rgbMax != -1) {
                        flag.set(false);
                    }
                });
                if (flag.get()) {
                    integer = i;
                    break;
                }
            }
        }
//        File outputFile = new File("output.png");
//        ImageIO.write(imageOne, "png", outputFile);
//        File outputFile2 = new File("output2.png");
//        ImageIO.write(imageAll, "png", outputFile2);
        return integer;
    }


    private static BufferedImage bufferedImage(String base) throws IOException {
        BASE64Decoder decoder = new BASE64Decoder();
        base = base.replaceAll(" ", "+").replace("data:image/jpeg;base64", "");
        byte[] buffer = decoder.decodeBuffer(base);
        for (int i = 0; i < buffer.length; i++) {
            if (buffer[i] < 0) {
                buffer[i] += (byte) 256;
            }
        }
        return ImageIO.read(new ByteArrayInputStream(buffer));
    }
}
